package db

import (
	"fmt"
	"quant/backend/conf"
	"quant/backend/constants"
	"quant/backend/entity"
	"sync"

	// _ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	"github.com/sirupsen/logrus"
	"xorm.io/xorm"
	"xorm.io/xorm/names"
)

var (
	engine *xorm.Engine
	err    error
	mutex  sync.Mutex
)

func GetMySQL() *xorm.Engine {
	mutex.Lock()
	defer mutex.Unlock()

	if engine == nil {
		if err := initMySQL(); err != nil {
			logrus.Error(err)
			return nil
		}
	}
	return engine
}

func initMySQL() error {
	logrus.Info("初始化数据库连接")
	// connStr := "postgres://%s:%s@%s:%d/%s?sslmode=disable;"
	connStr := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable",
		conf.Config.Database.Username,
		conf.Config.Database.Password,
		conf.Config.Database.Host,
		conf.Config.Database.Port,
		conf.Config.Database.Database)
	if engine, err = xorm.NewEngine("postgres", connStr); err != nil {
		logrus.
			WithField("HOST", conf.Config.Database.Host).
			WithField("DATABASE", conf.Config.Database.Database).
			WithField("USERNAME", conf.Config.Database.Username).
			WithField("PASSWORD", conf.Config.Database.Password).
			WithField("PORT", conf.Config.Database.Port).
			WithField("TimeZone", engine.TZLocation.String()).
			Errorf("创建数据库连接出错: %v", err.Error())
		err = fmt.Errorf("初始化数据库连接失败: %w", err)
		logrus.WithField("方法", "mysql.initMySQL").Error(err)
		return err
	}
	engine.ShowSQL(conf.Config.Database.ShowSQL)
	// engine.SetMaxIdleConns(conf.Config.Database.MaxIdle)
	// engine.SetMaxOpenConns(conf.Config.Database.MaxOpen)
	engine.TZLocation = constants.SysTimeLocation
	// engine.SetMapper(names.GonicMapper{})
	tbMapper := names.NewPrefixMapper(names.GonicMapper{}, "t_")
	engine.SetTableMapper(tbMapper)
	engine.SetColumnMapper(names.GonicMapper{})

	// 测试连接
	if err = engine.Ping(); err != nil {
		logrus.
			WithField("HOST", conf.Config.Database.Host).
			WithField("DATABASE", conf.Config.Database.Database).
			WithField("USERNAME", conf.Config.Database.Username).
			WithField("PORT", conf.Config.Database.Port).
			WithField("TimeZone", engine.TZLocation.String()).
			Errorf("数据库连接失败 :%v", err)
		return err
	} else {
		logrus.
			WithField("HOST", conf.Config.Database.Host).
			WithField("DATABASE", conf.Config.Database.Database).
			WithField("USERNAME", conf.Config.Database.Username).
			WithField("PORT", conf.Config.Database.Port).
			WithField("TimeZone", engine.TZLocation.String()).
			Info("数据库连接成功")
	}

	if err = syncDatabase(); err != nil {
		logrus.Error(err)
		return err
	}
	return nil
}

func syncDatabase() error {
	logrus.Info("开始同步数据库")
	if err := engine.Sync(
		new(entity.StockEntity),
		new(entity.ConfigEntity),
		new(entity.DailyEntity),
		new(entity.PreferredEntity)); err != nil {
		err = fmt.Errorf("sync error: %w", err)
		logrus.Error(err)
		return err
	}
	logrus.Info("同步数据库完成")
	return nil
}
